package com.event.binlog.component;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.event.binlog.iface.ITableSchemaService;
import com.event.binlog.properties.DbBinlogProperties;
import com.event.common.model.DbListenConfig;
import com.event.common.model.TableSchema;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Description Mysql Schema
 * @Author Bing
 * @Date 2025/1/17 17:27
 */
@Component
@ConditionalOnBean(DbBinlogProperties.class)
public class MysqlSchemaComponent {

    @Resource
    private DbBinlogProperties dbBinlogProperties;

    @Resource
    private Optional<ITableSchemaService> tableSchemaService;

    private DbListenConfig dbListenConfig;

    public DbListenConfig getDbListenConfig() {
        return dbListenConfig;
    }

    /**
     * 加载配置
     * @throws IOException
     */
    @PostConstruct
    public void init() throws IOException {
        // 业务需要实现ITableSchemaService，提供查询表结构服务
        if(!tableSchemaService.isPresent()){
            throw new RuntimeException("ITableSchemaService is not present");
        }
        reload();
    }

    /**
     * 加载表Schema
     * @param tableName
     */
    public void reloadSchema(String tableName){
        List<TableSchema> tableSchemaList = tableSchemaService.get().getTableColumns(dbListenConfig.getDbName(), tableName);
        if(CollUtil.isEmpty(tableSchemaList)){
            return;
        }
        // 设置最新的Schema
        Map<String,List<TableSchema>> tableSchemaMap = dbListenConfig.getTableSchemaMap();
        tableSchemaMap.put(tableName,tableSchemaList);
    }

    /**
     * 加载配置文件
     * @throws IOException
     */
    public void reload() throws IOException {
        // 读取配置文件
        String content = readConfig(dbBinlogProperties.getBinlogListenConfigPath());
        if(StrUtil.isBlank(content)){
            return;
        }
        // 将配置文件转换为对象
        TypeReference<DbListenConfig> typeReference = new TypeReference<DbListenConfig>() {};
        dbListenConfig = JSON.parseObject(content, typeReference);
        if(ObjectUtil.isNull(dbListenConfig)){
            return;
        }
        if(CollUtil.isEmpty(dbListenConfig.getTables())){
            return;
        }
        // 获取表和orm实体映射
        Map<String, JSONObject> tableMap = dbListenConfig.getTableMap();
        for(DbListenConfig.TableModel item : dbListenConfig.getTables()){
            if(StrUtil.isBlank(item.getTableName()) || StrUtil.isBlank(item.getMapPath())){
                continue;
            }
            // 读取orm实体配置文件
            String tempContent = readConfig(item.getMapPath());
            if(StrUtil.isBlank(tempContent)){
                continue;
            }
            // 获取表和orm实体映射
            tableMap.put(item.getTableName(), JSONObject.parseObject(tempContent));
            // 获取表结构
            reloadSchema(item.getTableName());
        }
    }

    /**
     * 将配置文件转换为对象
     * @param path
     * @throws IOException
     */
    private String readConfig(String path) throws IOException {
        ClassPathResource resource = new ClassPathResource(path);
        try (BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) {
            String content = br.lines().collect(Collectors.joining(System.lineSeparator()));
            return content;
        }
    }
}